package de.unibi.comet.ac;

import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.lang.IllegalStateException;
import de.unibi.comet.util.TreeNode;
import de.unibi.comet.util.EmptyIterator;

public class AhoCorasickNode implements java.lang.Comparable<Character>, TreeNode {

	private List<AhoCorasickNode> children;
	private char character;
	private int nr;
	private AhoCorasickNode failureLink;
	private int output;
	
	AhoCorasickNode(char c, int nr) {
		children = null;
		character = c;
		output=0;
		this.nr=nr;
	}

	public int compareTo(Character c) {
		if (character < c) return -1;
		if (character > c) return 1;
		return 0;
	}
	
	public Iterator<AhoCorasickNode> children() {
		if (children==null) return new EmptyIterator<AhoCorasickNode>();
		return children.iterator();
	}

	public boolean hasChild() {
		if (children==null) return false;
		return children.size()>0;
	}

	AhoCorasickNode getChildByChar(char c) {
		if (children==null) return null;
		int k = Collections.binarySearch(children, c);
		if (k>=0) return children.get(k);
		return null;
	}

	void addChild(AhoCorasickNode child) {
		if (children==null) {
			children=new ArrayList<AhoCorasickNode>(1);
			children.add(child);
			return;
		}
		if (child.character>=children.get(children.size()-1).character) {
			children.add(child);
		} else {
			throw new IllegalStateException("Children must be added in order");
		}
	}

	public String pstricksOutput() {
		String s = String.format("\\pstree[]{\\Tcircle[name=n%d]{%d}}{", nr, nr);
		if (children!=null) {
			for (AhoCorasickNode child : children) {
				String child_str = child.pstricksOutput();
				int k = child_str.indexOf("\\Tcircle");
				if (k>=0) k=child_str.indexOf("}",k);
				if (k>=0){
					s+=child_str.substring(0, k+1);
					s+="\\tlput{"+child.character+"}";
					s+=child_str.substring(k+1);
				}
			}
		}
		if (failureLink!=null) {
			s+=String.format("\\psset{linestyle=dotted}\\Tcircle{%d}",failureLink.getNr());
		}
//		if self.failure_link!=None:
//			s+="\\psset{linestyle=dotted}\\Tcircle{%d,%d}"%(self.failure_link[0].nr,self.failure_link[1])
		s+='}';
		return s;
	}

	int countNodes() {
		int i = 1;
		if (children!=null) {
			for (AhoCorasickNode node : children) {
				i+=node.countNodes();
			}
		}
		return i;
	}

	public char getCharacter() {
		return character;
	}

	public int getNr() {
		return nr;
	}

	public AhoCorasickNode getFailureLink() {
		return failureLink;
	}

	public void setFailureLink(AhoCorasickNode failureLink) {
		this.failureLink = failureLink;
	}

	public int getOutput() {
		return output;
	}

	public void setOutput(int output) {
		this.output = output;
	}
}
